<template>
  <view v-if="layoutPos.layout === 'FLEX'" :class="colClass" :style="flexStyle">
    <slot></slot>
  </view>
  <uni-col
    v-else
    :class="colClass"
    :style="cssVars"
    :span="gridAttrs.span"
    :offset="gridAttrs.offset"
  >
    <slot></slot>
  </uni-col>
</template>
<script setup lang="ts">
import { ILayoutPos, IGridLayoutPos, IFlexLayoutPos } from '@ibiz/model-core'
import { useNamespace } from '@/use'
import { calcGridLayoutPos, IColState } from '@ibiz-template/runtime'

const ns = useNamespace('col')

const props = defineProps({
  layoutPos: {
    type: Object as PropType<ILayoutPos>,
    required: true,
  },
  state: {
    type: Object as PropType<IColState>,
    required: true,
  },
})

/**
 * 计算间距类名
 */
const spacingClass = computed(() => {
  const ns2 = useNamespace('spacing')
  const classArr: string[] = []
  const spacings: IData = {
    top: props.layoutPos.spacingTop,
    bottom: props.layoutPos.spacingBottom,
    left: props.layoutPos.spacingLeft,
    right: props.layoutPos.spacingRight,
  }
  Object.keys(spacings).forEach((position) => {
    const value = spacings[position] as string
    if (!value) {
      return
    }
    classArr.push(ns2.bm(position, value.toLowerCase()))
  })
  return classArr
})

// 计算栅格布局的属性
const gridAttrs = computed(() => {
  const gridLayoutPos = props.layoutPos as IGridLayoutPos
  // FLEX布局时不计算
  if (gridLayoutPos.layout === 'FLEX') {
    return {}
  }
  const { md } = calcGridLayoutPos(gridLayoutPos)

  return {
    span: md.span,
    offset: md.offset,
  }
})

const cssVars = computed(() => {
  if (props.state) {
    const layout = props.state.layout
    const styles = {
      width: layout.width,
      height: layout.height,
    }
    Object.assign(styles, layout.extraStyle)
    return styles
  }
  return ''
})

const colClass = computed(() => {
  const classNames: string[] = [
    ns.b(),
    props.layoutPos?.layout === 'FLEX' ? ns.m('flex') : ns.m('grid'),
    ...spacingClass.value,
  ]
  if (props.state) {
    classNames.push(
      ns.is('hidden', !props.state.visible),
      props.state.layout.extraClass as unknown as string,
    )
  }
  return classNames
})

const flexStyle = computed(() => {
  return {
    flexGrow: (props.layoutPos as IFlexLayoutPos).grow || '',
    flexShrink:
      (props.layoutPos as IFlexLayoutPos).shrink === 1
        ? ''
        : (props.layoutPos as IFlexLayoutPos).shrink || '',
    flexBasis: `${(props.layoutPos as IFlexLayoutPos).basis || ''}px}`,
    ...cssVars,
  }
})
</script>
<style lang="scss">
@include b(col) {
  @include m(flex) {
    min-width: 0;

    // 修复flex时flex-grow和flex-shrink时高度被内容撑开，没法压缩
    min-height: 0;
  }

  @include when(hidden) {
    display: none;
  }
}

@include b(spacing-top) {
  @include m(outersmall) {
    margin-top: getCssVar(spacing, tight);
  }

  @include m(outermedium) {
    margin-top: getCssVar(spacing, base);
  }

  @include m(outerlarge) {
    margin-top: getCssVar(spacing, loose);
  }

  @include m(outernone) {
    margin-top: getCssVar(spacing, none);
  }

  @include m(innersmall) {
    padding-top: getCssVar(spacing, tight);
  }

  @include m(innermedium) {
    padding-top: getCssVar(spacing, base);
  }

  @include m(innerlarge) {
    padding-top: getCssVar(spacing, loose);
  }

  @include m(innernone) {
    padding-top: getCssVar(spacing, none);
  }
}

@include b(spacing-bottom) {
  @include m(outersmall) {
    margin-bottom: getCssVar(spacing, tight);
  }

  @include m(outermedium) {
    margin-bottom: getCssVar(spacing, base);
  }

  @include m(outerlarge) {
    margin-bottom: getCssVar(spacing, loose);
  }

  @include m(outernone) {
    margin-bottom: getCssVar(spacing, none);
  }

  @include m(innersmall) {
    padding-bottom: getCssVar(spacing, tight);
  }

  @include m(innermedium) {
    padding-bottom: getCssVar(spacing, base);
  }

  @include m(innerlarge) {
    padding-bottom: getCssVar(spacing, loose);
  }

  @include m(innernone) {
    padding-bottom: getCssVar(spacing, none);
  }
}

@include b(spacing-left) {
  @include m(outersmall) {
    margin-left: getCssVar(spacing, tight);
  }

  @include m(outermedium) {
    margin-left: getCssVar(spacing, base);
  }

  @include m(outerlarge) {
    margin-left: getCssVar(spacing, loose);
  }

  @include m(outernone) {
    margin-left: getCssVar(spacing, none);
  }

  @include m(innersmall) {
    padding-left: getCssVar(spacing, tight);
  }

  @include m(innermedium) {
    padding-left: getCssVar(spacing, base);
  }

  @include m(innerlarge) {
    padding-left: getCssVar(spacing, loose);
  }

  @include m(innernone) {
    padding-left: getCssVar(spacing, none);
  }
}

@include b(spacing-right) {
  @include m(outersmall) {
    margin-right: getCssVar(spacing, tight);
  }

  @include m(outermedium) {
    margin-right: getCssVar(spacing, base);
  }

  @include m(outerlarge) {
    margin-right: getCssVar(spacing, loose);
  }

  @include m(outernone) {
    margin-right: getCssVar(spacing, none);
  }

  @include m(innersmall) {
    padding-right: getCssVar(spacing, tight);
  }

  @include m(innermedium) {
    padding-right: getCssVar(spacing, base);
  }

  @include m(innerlarge) {
    padding-right: getCssVar(spacing, loose);
  }

  @include m(innernone) {
    padding-right: getCssVar(spacing, none);
  }
}
</style>
